<script>
    /* 
        1.对象字面量
        2.new Object()
        3.工厂函数
        4.构造函数
        5.原型模式
        6.组合模式（构造函数+原型）
    */

   const o1 = {
       name:"对象字面量",
       sayName:function(){
           console.log(this.name);
       }
    }
    console.dir(o1)

   const o2 = new Object();
   o2.name = 'new对象的方式';
   o2.sayName = function(){
       console.log(this.name);
   }
   console.dir(o2)
   console.log(Object.prototype.toString.call(o2));

   o3Name = '工厂函数创建的对象'
   function createObj(name){
       const o3 = new Object();
       o3.name = name;
       o3.sayName = function(){
           console.log(this.name);
       }
       return o3
   }
   console.log(Object.prototype.toString.call(createObj(o3Name)));
   console.log(createObj(o3Name));

/* 解决instanceof 无法识别对象类型 
   缺点：
   每个方法都有在每个实例上重新创建一遍。person1和person2都有一个sayName()的方法，但两个方法不是同一个Function实例。不同实例上的同名函数是不相等的。 
创建两个完成同样任务的Function实例没有必要，而且还有this对象在，不需要在执行代码前就把函数绑定在特定对象上，可以像下面这样。 
*/
   o4Name = '构造函数创建的对象'
   function O4(name){
       this.name = name;
       this.sayName = function(){
           console.log(this.name);
       }
   }

   const o4 = new O4(o4Name);
   console.log(o4);
   console.log(Object.prototype.toString.call(o4));
   console.log(o4 instanceof  O4);

   /* 原型模式 
   解决实例化时创建多个函数，共享属性和方法

   原型模式最大问题是由其共享的本性所导致的。  
    对于包含引用类型值的属性来说，问题较为突出 
   两个对象，修改其中一个的原型属性时，另外一个也变化
   */
   function O5(){

   }
   O5.prototype.name='原型模式创建对象'
   O5.prototype.sayName = function(){
       console.log(this.name);
   }
   const o5 = new O5();
   console.log(o5);
   console.dir(O5)

   /* 
    组合模式
   */
  let o6Name = '组合模式创建对象'
  function O6(name){
      this.name = name;
      
  }
//   定义共享属性方法
// 创建自定义类型的最常用的方式，就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性，原型模式用于定义方法和共享的属性，这样每个实例都有自己的一份实例属性的副本，又同时共享着对方法的引用，最大限度的节省了内存。 
  O6.prototype = {
    //   指定构造函数
    construtor:O6,
    sayName : function(){
          console.log(this.name);
      }
  }

  const o6 = new O6(o6Name);
  console.log(o6);






</script>

